package com.koron.css2.contractmanage.service;

import com.koron.css2.ApplicationConfig;
import com.koron.css2.common.utils.DateUtils;
import com.koron.css2.contractmanage.vo.UserInfoVO;
import com.koron.css2.serviceManage.utils.JsonUtils;
import net.qiyuesuo.v3sdk.SdkClient;
import net.qiyuesuo.v3sdk.common.utils.StringUtils;
import net.qiyuesuo.v3sdk.model.common.DetailContract;
import net.qiyuesuo.v3sdk.model.common.Signatory;
import net.qiyuesuo.v3sdk.model.common.SimpleDocumentParam;
import net.qiyuesuo.v3sdk.model.contract.request.*;
import net.qiyuesuo.v3sdk.model.document.request.DocumentDownloadRequest;
import net.qiyuesuo.v3sdk.utils.SdkResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

@Service
public class EcContratServiceImpl extends AbstractEcContratService {
    private static Logger logger = LoggerFactory.getLogger(EcContratServiceImpl.class);

    private static final String SERVER_URL = ApplicationConfig.privateEcUrl;
    private static final String ACCESS_KEY = ApplicationConfig.privateEcToken;
    private static final String ACCESS_SECRET = ApplicationConfig.privateEcSecret;

    private static final String COMPANY = "COMPANY";
    private static final String PERSONAL = "PERSONAL";

    /**
     *
     * @param userInfoVO
     * @return
     */
    @Override
    public SdkResponse<String> ecContractCreat(UserInfoVO userInfoVO, String ecPeCategoryId,
                                                 String ecCoCategoryId, String ecCompanyName) throws Exception{
        // 初始化sdkClient
        SdkClient sdkClient = new SdkClient(SERVER_URL, ACCESS_KEY, ACCESS_SECRET);
        // 合同基本参数
        ContractCreatebycategoryRequest contract = new ContractCreatebycategoryRequest();


        String certType = userInfoVO.getCertType();
        String categoryId;
        String tenantType;
        // 企业用水，8：统一社会信用代码，6：营业执照
        if ("8".equals(certType)|| "6".equals(certType)) { //企业用水
            categoryId = ecCoCategoryId;
            tenantType = COMPANY;
        } else {
            categoryId = ecPeCategoryId;
            tenantType = PERSONAL;
        }
        contract.setSubject("供用水合同（" + userInfoVO.getName() + "）");
        contract.setCategoryId(categoryId);
        contract.setTenantName(ecCompanyName);
        contract.setSend(true);

        // 第一行，接收方
        Signatory signatory1 = new Signatory();
        signatory1.setTenantName(userInfoVO.getName());
        signatory1.setTenantType(tenantType);
        signatory1.setReceiverName(userInfoVO.getName());
        signatory1.setContact(userInfoVO.getMobile());

        // 第二行，发起方
        Signatory signatory2 = new Signatory();
        signatory2.setTenantName(ecCompanyName);
        signatory2.setTenantType(COMPANY);
        List<Signatory> signatories = new ArrayList<>();
        // 设置签署方
        signatories.add(signatory1);
        signatories.add(signatory2);
        contract.setSignatories(signatories);

        // 设置模板参数
        Map<String, String> paramMap = new HashMap<>();
        // 合同编号
        paramMap.put("contractNo", userInfoVO.getContractNo());
        // 户号
        paramMap.put("userNo", userInfoVO.getUserNo());
        // 乙方名称
        paramMap.put("name", userInfoVO.getName());
        // 身份证号或统一社会信用代码
        paramMap.put("certNo", userInfoVO.getCertNo());
        // 手机
        paramMap.put("mobile", userInfoVO.getMobile());
        // 客户地址
        paramMap.put("ctmAddr", userInfoVO.getCtmAddr());

        // 乙方用水地址（必填）
        String yfysdz = StringUtils.trimToEmpty(userInfoVO.getClientContractAddr()) +
                StringUtils.trimToEmpty(userInfoVO.getClientContractAddrDetail());
        paramMap.put("yfysdz", StringUtils.isEmpty(yfysdz) ? "/" : yfysdz);
        // 乙方用水性质（必填）
        paramMap.put("yfysxz", "/");
        // 水表数量（必填）
        paramMap.put("sbsl", "1");
        // 表径DN（必填）
        paramMap.put("bjDN", userInfoVO.getBjDN());
        // 水费结算方式：现金缴款/微信支付/银行代扣/银行转账（单选必填）
        paramMap.put("sfjsfs", "/"); // pjInfoBean.getPrepayType()
        // 分界点：甲方安装的注册登记的计费水表处/进入建筑物前阀门处/其他（单选必填）
        paramMap.put("fjd", "/");
        // 其他补充填写（非必填） 注释：分界点选择《其他》选项时，《其他补充填写》项必填
        paramMap.put("qtbctx", "/");
        // 接收电话（必填）
        paramMap.put("lxdh", userInfoVO.getMobile());
        // 电子邮件（必填）
        paramMap.put("dzyj", "/");
        // 补充条款（非必填）
        paramMap.put("bctk", "/");
        // 报装编号（必填）
        paramMap.put("bzbh", userInfoVO.getBillNo());
        // 签订日期（必填）
        paramMap.put("qdrq", DateUtils.parseDate(new Date(), "yyyy-MM-dd"));
        // 用水四至范围
        paramMap.put("ysszfw", "/");
        // 执行类别
        paramMap.put("zxlb", "/");
        // 预购方式选项一：（1）经双方友好协商，同意采用分期预购水费（单选非必填）
        paramMap.put("fqygsf", "/");
        // 标准预付额度（非必填） 注释：选择《预购方式选项一》则《标准预付额度》参数必填
        paramMap.put("bzyfed", "/");
        // 预购方式选项二：（2）经双方友好协商，同意采用一次性预购水费再用水作为水费结算方式（单选非必填）
        paramMap.put("ycxygsf", "/");
        // 标准年度预付额度（非必填） 注释：选择《预购方式选项二》则《标准年度预付额度》参数必填
        paramMap.put("bzndyfed", "/");

        //增加 ：乙方缴费方式 、水表装表地址、客户编号--总表得客户编号、移动电话、通知人手机、固定电话、水表类型、抄表周期、抄表日、电子邮件
        //乙方缴费方式（必填）
        paramMap.put("payWay",userInfoVO.getPayWay() );
        //水表装表地址（必填）
        paramMap.put("setupMeterAddr",userInfoVO.getSetupMeterAddr() );
        //总表得客户编号
        paramMap.put("fatherCtmNo",userInfoVO.getFatherCtmNo());
        //客户编号
        paramMap.put("ctmNo",userInfoVO.getCtmNo());
        //移动电话
        paramMap.put("mobile",userInfoVO.getMobile());
        //通知人手机
        paramMap.put("stopWaterLinkMobile",userInfoVO.getStopWaterLinkMobile());
        //固定电话
        paramMap.put("linkTel",userInfoVO.getLinkTel());
        //水表类型(必填)
        paramMap.put("meterType",userInfoVO.getMeterType());
        //抄表周期(必填)
        paramMap.put("meterReadingCycle",userInfoVO.getMeterReadingCycle());
        //抄表日
        paramMap.put("meterReadingDay",userInfoVO.getMeterReadingDay());
        //电子邮件
        paramMap.put("email",userInfoVO.getEmailAddr());

        List<SimpleDocumentParam> SimpleparamMap =new ArrayList<>();
        Iterator<Map.Entry<String, String>> iterator = paramMap.entrySet().iterator();
        while (iterator.hasNext()) {
            SimpleDocumentParam documentParam = new SimpleDocumentParam();
            Map.Entry<String, String> entry = iterator.next();
            documentParam.setName(entry.getKey());
            documentParam.setValue(entry.getValue());
            SimpleparamMap.add(documentParam);
        }
        logger.debug("contract：" + JsonUtils.objectToJson(contract));
        contract.setDocumentParams(SimpleparamMap);

        SdkResponse<String> responseObj = sdkClient.service(contract, String.class);


        return responseObj;
    }

    /**
     *
     * @param fileId
     * @return
     */
    @Override
    public byte[] ecContractDownLoad(Long fileId) throws Exception{
        SdkClient sdkClient = new SdkClient(SERVER_URL, ACCESS_KEY, ACCESS_SECRET);
        // 下载合同文档
        DocumentDownloadRequest request = new DocumentDownloadRequest();
        request.setDocumentId(fileId);
        ByteArrayOutputStream fos = new ByteArrayOutputStream();
        try {
        sdkClient.download(request, fos);
            byte[] bytes = fos.toByteArray();
            return bytes;
        }
        catch (Exception e) {
            log.error(fileId + "预览电子合同失败！", e);
            return null;
        }
        finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                log.error("PrivateEcContratPreview流关闭失败：", e);
            }
        }
    }

    /**
     * 撤回合同
     * @param contractId
     * @param userInfoVO
     * @return
     * @throws Exception
     */
    @Override
    public SdkResponse ecContractRecalled(Long contractId, UserInfoVO userInfoVO) throws Exception {
        // 初始化sdkClient
        SdkClient sdkClient = new SdkClient(SERVER_URL, ACCESS_KEY, ACCESS_SECRET);
        // “签署中”状态下撤回合同
        ContractRecallRequest request = new ContractRecallRequest();
        request.setContractId(contractId);
        request.setReason("撤回合同");

        SdkResponse response = sdkClient.service(request);

        return response;
    }

    /**
     * 作废合同
     * @param contractId
     * @return
     * @throws Exception
     */
    @Override
    public SdkResponse ecContractCancel(Long contractId) throws Exception {
        SdkClient sdkClient = new SdkClient(SERVER_URL, ACCESS_KEY, ACCESS_SECRET);
        ContractInitiateCancelRequest request = new ContractInitiateCancelRequest();
        request.setContractId(contractId);
        request.setReason("作废合同");
        SdkResponse response = sdkClient.service(request);
        return response;
    }

    /**
     * 合同催签
     * @param contractId
     * @return
     * @throws Exception
     */
    @Override
    public SdkResponse ecContractNotify(Long contractId) throws Exception {
        // 初始化sdkClient
        SdkClient sdkClient = new SdkClient(SERVER_URL, ACCESS_KEY, ACCESS_SECRET);
        // 合同催签
        ContractNotifyRequest request = new ContractNotifyRequest();
        request.setContractId(contractId);
        SdkResponse response = sdkClient.service(request);
        return response;
    }

    /**
     * 根据合同ID获取合同文件信息
     * @return
     * @throws Exception
     */
    @Override
    public SdkResponse<DetailContract> getEcContractDetail(Long contractId) throws Exception {
        SdkClient sdkClient = new SdkClient(SERVER_URL, ACCESS_KEY, ACCESS_SECRET);
        ContractDetailRequest request = new ContractDetailRequest ();
        request.setContractId(contractId);
        SdkResponse<DetailContract> response = sdkClient.service(request, DetailContract.class);
        return response;
    }

}
